package com.gruuf.done.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Application implements EntryPoint, ValueChangeHandler<String> {

    private static final String ACTIVE_TASKS_CLICKED = "activeTasksLink";
    private static final String FINISHED_TASKS_CLICKED = "finishedTasksLink";

    private static final String SHOWING_ACTIVE_TASKS = "Showing active tasks";
    private static final String SHOWING_FINISHED_TASKS = "Showing finished tasks";

    private static final String FIELD_SECTION = "fieldSection";

    private Label historyLabel;

    private TextBox taskName;
    private TextArea taskDescription;
    private TextBox taskType;
    private DateBox taskEnd;
    private Map<String, SimpleTask> tasks;
    private HorizontalPanel taskListsPanel;

    public void onModuleLoad() {
        tasks = new HashMap<String, SimpleTask>();
        createTaskForm();
        createTaskStateLinks();
        createTaskLists();
    }

    private void createTaskStateLinks() {
        HorizontalPanel linkPanel = new HorizontalPanel();
        linkPanel.add(new Hyperlink("Active tasks", ACTIVE_TASKS_CLICKED));
        linkPanel.add(new Hyperlink("Finished tasks", FINISHED_TASKS_CLICKED));
        historyLabel = new Label(SHOWING_ACTIVE_TASKS);
        historyLabel.addStyleName("historyLabel");
        linkPanel.add(historyLabel);
        RootPanel.get("taskStateLinks").add(linkPanel);
        History.addValueChangeHandler(this);
        History.fireCurrentHistoryState();        
    }

    private void createTaskForm() {
        HorizontalPanel formPanel = new HorizontalPanel();
        formPanel.addStyleName("formPanel");
        formPanel.add(createFormSectionA());
        formPanel.add(createFormSectionB());
        RootPanel.get("taskForm").add(formPanel);
    }

    private VerticalPanel createFormSectionB() {
        VerticalPanel formSectionB = new VerticalPanel();
        formSectionB.add(new Label("Description"));
        taskDescription = new TextArea();
        taskDescription.setCharacterWidth(40);
        taskDescription.setVisibleLines(12);
        formSectionB.add(taskDescription);
        createAddButtonPanel(formSectionB);
        return formSectionB;
    }

    private void createAddButtonPanel(VerticalPanel formSectionB) {
        HorizontalPanel addButtonPanel = new HorizontalPanel();
        addButtonPanel.addStyleName("addButtonPanel");
        Button addButton = new Button("Add");
        addButtonPanel.add(addButton);
        addButton.addStyleName("addButton");
        addButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent clickEvent) {
                SimpleTask task = new SimpleTask(taskName.getValue(), taskType.getValue(), taskEnd.getValue(), taskDescription.getValue());
                tasks.put(taskName.getValue(), task);
                loadTasks();
            }
        });
        formSectionB.add(addButtonPanel);
    }

    private void loadTasks() {
        taskListsPanel.clear();
        for (String type : getTaskTypes()) {
            VerticalPanel typePanel = new VerticalPanel();
            typePanel.addStyleName("typePanel");
            typePanel.add(new Label(type));
            int row = 0;
            SimpleTask[] tasksByType = getTasksByType(type);
            Grid grid = new Grid(tasksByType.length, 4);
            for (final SimpleTask task : tasksByType) {
                grid.setText(row, 0, task.getName());
                if (task.getEndDate() == null) {
                    grid.setText(row, 1, "in progress");
                } else {
                    DateTimeFormat format = DateTimeFormat.getMediumDateFormat();
                    grid.setText(row, 1, format.format(task.getEndDate()));
                }
                Button done = new Button("v");
                done.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent clickEvent) {
                        task.finish();
                        loadTasks();
                    }
                });
                grid.setWidget(row, 2, done);
                Button delete = new Button("x"); 
                delete.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent clickEvent) {
                        if (tasks.containsKey(task.getName())) {
                            tasks.remove(task.getName());
                            loadTasks();
                        }
                    }
                });
                grid.setWidget(row, 3, delete);
                row++;
            }
            typePanel.add(grid);
            taskListsPanel.add(typePanel);
        }
    }

    private VerticalPanel createFormSectionA() {
        VerticalPanel formSectionA = new VerticalPanel();
        createTaskSection(formSectionA);
        createTypeSection(formSectionA);
        createEndSection(formSectionA);
        return formSectionA;
    }

    private void createTaskSection(VerticalPanel formSectionA) {
        HorizontalPanel taskPanel = new HorizontalPanel();
        taskPanel.addStyleName(FIELD_SECTION);
        taskPanel.add(new Label("Task"));
        taskName = new TextBox();
        taskPanel.add(taskName);
        formSectionA.add(taskPanel);
    }

    private void createTypeSection(VerticalPanel formSectionA) {
        HorizontalPanel typePanel = new HorizontalPanel();
        typePanel.addStyleName(FIELD_SECTION);
        typePanel.add(new Label("Type"));
        taskType = new TextBox();
        typePanel.add(taskType);
        formSectionA.add(typePanel);
    }

    private void createEndSection(VerticalPanel formSectionA) {
        HorizontalPanel endPanel = new HorizontalPanel();
        endPanel.addStyleName(FIELD_SECTION);
        endPanel.add(new Label("End"));
        taskEnd = new DateBox();
        taskEnd.setFormat(new DateBox.DefaultFormat(DateTimeFormat.getMediumDateFormat()));
        endPanel.add(taskEnd);
        formSectionA.add(endPanel);
    }

    private void createTaskLists() {
        taskListsPanel = new HorizontalPanel();
        loadTasks();
        RootPanel.get("taskLists").add(taskListsPanel);
    }

    private SimpleTask[] getTasksByType(String type) {
        Set<SimpleTask> tasks = new HashSet<SimpleTask>();
        for (SimpleTask task : this.tasks.values()) {
            if (type.equals(task.getType())) {
                tasks.add(task);
            }
        }
        return tasks.toArray(new SimpleTask[tasks.size()]);
    }

    private String[] getTaskTypes() {
        Set<String> types = new HashSet<String>();
        for (SimpleTask task : tasks.values()) {
            if (!types.contains(task.getType())) {
                types.add(task.getType());
            }
        }
        return types.toArray(new String[types.size()]);
    }

    public void onValueChange(ValueChangeEvent valueChangeEvent) {
        if (ACTIVE_TASKS_CLICKED.equals(valueChangeEvent.getValue())) {
            historyLabel.setText(SHOWING_ACTIVE_TASKS);
        }
        if (FINISHED_TASKS_CLICKED.equals(valueChangeEvent.getValue())) {
            historyLabel.setText(SHOWING_FINISHED_TASKS);
        }
    }

}
